package com.adee.java.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class GroupChatServer {
    // 聊天室成员
    Map<String, SocketChannel> memberChannels;
    // 端口
    private static final int PORT = 8000;
    // 选择器
    private Selector selector;
    // 监听管道
    private ServerSocketChannel serverSocketChannel;
    // 缓冲
    private Buffer buffer;

    public GroupChatServer() throws IOException {
        // 初始化Selector选择器
        this.selector = Selector.open();
        // 初始化serverSocketChannel
        this.serverSocketChannel = createServerSocketChannel(selector);
        // 初始化Buffer 1k
        this.buffer = ByteBuffer.allocate(1024);
        // 初始化聊天室成员列表
        memberChannels = new ConcurrentHashMap<>();
    }

    // 创建serverSocketChannel，并注册到selector上
    private ServerSocketChannel createServerSocketChannel(Selector selector) throws IOException{
        // 新建一个ServerSocketChannel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // serverSocketChannel设置为非阻塞
        serverSocketChannel.configureBlocking(false);
        // serverSocketChannel注册到selector上
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        // serverSocketChannel绑定端口
        serverSocketChannel.bind(new InetSocketAddress(PORT));
        return serverSocketChannel;
    }

    // 启动监听
    public void listen() throws IOException {
        System.out.println("启动服务端监听...");
        Selector sel = this.selector;
        ByteBuffer buff = (ByteBuffer) this.buffer;
        try {
            for(;;) {
                int count = sel.select();
                if(count == 0) continue;
                // 获取事件Key集合，每次调用selector.select()方法都返回一个全新的Set<SelectionKey>集合
                Set<SelectionKey> selectionKeys = sel.selectedKeys();
                Iterator<SelectionKey> iter = selectionKeys.iterator();
                while (iter.hasNext()) {
                    SelectionKey selectionKey = iter.next();
                    iter.remove(); // 删除当前事件key，避免下次循环重用
                    SelectableChannel channel = selectionKey.channel();
                    if(selectionKey.isAcceptable()) {
                        ServerSocketChannel ssc = (ServerSocketChannel)channel;
                        SocketChannel socketChannel = ssc.accept();
                        socketChannel.configureBlocking(false);
                        socketChannel.register(sel, SelectionKey.OP_READ);
                        System.out.println("客户端连接成功：ip=" + socketChannel.socket().getInetAddress()
                            + ", port=" + socketChannel.socket().getPort());
                    } else if(selectionKey.isReadable()) {
                        SocketChannel sc = (SocketChannel)channel;
                        buff.clear();
                        sc.read(buff);
                        buff.flip(); // 准备读buffer，广播写入其他通道
                        for(SelectionKey k : sel.keys()) { // 所有注册到selector上的channel
                            if(k.channel() instanceof ServerSocketChannel) continue;
                            // if(k == selectionKey) continue;
//                            if(k.isWritable()) {
//                                buff.rewind(); // 从头重新读
//                                SocketChannel wsc = (SocketChannel)k.channel();
//                                wsc.write(buff);
//                            }
                            buff.rewind(); // 从头重新读
                            SocketChannel wsc = (SocketChannel)k.channel();
                            wsc.write(buff);
                        }
                    }

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        }
    }

    public static void main(String[] args) throws IOException {
        new GroupChatServer().listen();
    }
}
